﻿using System;
using System.Data;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using SimpleCore;

namespace SimpleEditor.ExcelTool
{
    public class ConfigDataCodeCreator
    {
        [MenuItem("Simple Tools/Config Data/Auto Create Code")]
        static void CreateCodes()
        {
            Debug.Log("start create !!!");

            ConfigCodePath = LoadConfigCodePath();
            
            string codeTemp = GetCodeTemplate();
            string[] split = codeTemp.Split('-');
            _classTemp = split[0];
            _attrTemp = split[1];

            var files = GetExcelFiles();

            for (int i = 0; i < files.Length; i++)
            {
                var excelData = ExcelReaderHelper.Read(files[i]);
                CreateCode(files[i], excelData);
            }
            
            Debug.Log("create finished !!!");
        }

        static string LoadConfigCodePath()
        {
            var data = AssetDatabase.LoadAssetAtPath<ExcelToolConfigAssetData>(ToolConfigPath);
            return data.CodePath;
        }

        static string[] GetExcelFiles()
        {
            string path = $"{Application.dataPath.Replace("Assets", "")}Excel/";
            var files = Directory.GetFiles(path).Where(a => a.EndsWith(".xls") || a.EndsWith(".xlsx")).ToArray();

            return files;
        }

        static string GetCodeTemplate()
        {
            string path = $"{Application.dataPath}/SimpleEditor/Editor/ExcelTool/ConfigDataCode.txt";
            string content = FileTool.Read(path);
            return content;
        }

        static void CreateCode(string fileName, DataSet dataSet)
        {
            Debug.Log(fileName);
            try
            {
                var table = dataSet.Tables[0];
                var describtionLine = table.Rows[0];
                var attrNameLine = table.Rows[1];
                var typeLine = table.Rows[2];
                var defaultLine = table.Rows[3];

                string attrContents = "";
                
                //第一列是Id，跳过
                for (int i = 1; i < attrNameLine.ItemArray.Length; i++)
                {
                    string attrName = attrNameLine[i].ToString();
                    if (string.IsNullOrEmpty(attrName)) continue;
                    string typeName = typeLine[i].ToString();
                    if(string.IsNullOrEmpty(typeName)) continue;
                    string describtion = describtionLine[i].ToString();
                    string defaultContent = defaultLine[i].ToString();
                    
                    NormalizeTypeAndDefaultValue(ref typeName, ref defaultContent);

                    string attrTemp = _attrTemp;
                    attrTemp = attrTemp.Replace("#DESCRIBTION#", describtion);
                    attrTemp = attrTemp.Replace("#TYPE#", typeName);
                    attrTemp = attrTemp.Replace("#ATTRNAME#", attrName);
                    attrTemp = attrTemp.Replace("#DEFAULT#", defaultContent);
                    attrTemp = attrTemp.Replace("\\t", "\t");

                    attrContents += attrTemp;
                }

                string classTemp = _classTemp;
                classTemp = classTemp.Replace("#ATTRS#", attrContents);

                fileName = Path.GetFileNameWithoutExtension(fileName);
                classTemp = classTemp.Replace("#EXCELNAME#", fileName);
                 
                var fullPath = PathTool.GetFullPath($"{ConfigCodePath}/{fileName}.cs");
                FileTool.Write(fullPath, classTemp);
                Debug.Log("success !!");
                
                AssetDatabase.Refresh();
            }
            catch (Exception e)
            {
                Debug.LogError(e);
                throw;
            }
        }

        static void NormalizeTypeAndDefaultValue(ref string typeName, ref string defaultValue)
        {
            string[] split = string.IsNullOrEmpty(defaultValue) ? new string[0] : defaultValue.Split('|');
            string temp = "";
            switch (typeName.ToUpper())
            {
                case "INT":
                    typeName = "int";
                    defaultValue = defaultValue == "" ? "-1" : Convert.ToInt32(defaultValue).ToString();
                    break;
                case "FLOAT":
                    typeName = "float";
                    defaultValue = defaultValue == "" ? "-1" : Convert.ToSingle(defaultValue).ToString();
                    break;
                case "STRING":
                    typeName = "string";
                    defaultValue = $"\"{defaultValue}\"";
                    break;
                case "BOOL":
                    typeName = "bool";
                    defaultValue = defaultValue == "" ? "false" : Convert.ToBoolean(defaultValue).ToString();
                    break;
                case "LIST<INT>":
                    typeName = "List<int>";
                    for (int i = 0; i < split.Length; i++)
                    {
                        var value = Convert.ToInt32(split[i]).ToString();
                        temp = temp + value + ",";
                    }
                    defaultValue = $"new {typeName}() {temp}"; 
                    break;
                case "LIST<FLOAT>":
                    typeName = "List<float>";
                    for (int i = 0; i < split.Length; i++)
                    {
                        var value = Convert.ToSingle(split[i]).ToString();
                        temp = temp + value + ",";
                    }
                    defaultValue = $"new {typeName}() {temp}"; 
                    break;
                case "LIST<STRING>":
                    typeName = "List<string>";
                    for (int i = 0; i < split.Length; i++)
                    {
                        var value = $"\"{defaultValue}\"";
                        temp = temp + value + ",";
                    }
                    defaultValue = $"new {typeName}() {temp}"; 
                    break;
                case "LIST<BOOL>":
                    typeName = "List<bool>";
                    for (int i = 0; i < split.Length; i++)
                    {
                        var value = Convert.ToBoolean(split[i]).ToString();
                        temp = temp + value + ",";
                    }
                    defaultValue = $"new {typeName}() {temp}"; 
                    break;
                default:
                    Debug.LogError($"other type, need extend !!!  {typeName}");                    
                    break;
            }
        }

        private const string ToolConfigPath = "Assets/SimpleEditor/Editor/ExcelTool/ExcelToolConfigData.asset";
        private static string ConfigCodePath = "/Script/Data/ConfigData";
        private static string _classTemp;
        private static string _attrTemp;
    }
}

/// Excel 规范
/// ---------------
/// 行：
/// 行1：属性描述
/// 行2：字段名字
/// 行3：字段类型
/// 行4：默认值
/// ---------------
/// 列：
/// 列1：字段名：Id，类型：int
/// ---------------
/// 
///
///
/// 
